Buckle up, boys and girls, this might be a long story. This will be written mostly like a long rambling blog post.
But oh, sit right back, and I will tell you the tale...
The tale of how I ended up giving away money at the Karamja docks on my weekends.
Also, keep in mind that this is all recalled from memory and looking at old versions of my give-away code. I could be remembering specific dates wrong, but I think for the most part, I'm generally accurate.
Yeah, that's right. It all started that long ago. Remember March 2020? I sure do. The entire world was running around trying to figure out what to do about COVID. And thanks to that, I got to stay home from work for two whole weeks and get paid for it. How else to spend those two weeks than on Old School Runescape?
My entire Runescape career I've loved attempting to host a drop party, or just give money away in general, but I'd never really had enough money to give away. And when I did give money away, it was just a cluster of people trading me, asking for more, getting mad, etc. If you've ever tried to give money away I'm sure you've experienced this.
Well, anyway, while I was home basking in my mandatory isolation, I decided to try and do a little give away at the grand exchange. I always enjoyed goodiebags, so I tried to do my own (affordable) version. If I remember correctly, my inventory had 14 adamant scimitars, 6 rune scimitars, some rune 2hs, maybe a rune set, coins, and a bond.
If you don't know what a goodiebag is, you choose a number (usually 1-28), and whatever item in the hosts' inventory slot of the same number you chose, is the prize you get. For example, if you chose 4, you'd get whatever was in the top-right corner of my inventory. 28 would be bottom-right.
-
The goodiebag was a lot of fun, albeit high-maintenance. I kept running into problems that really made giving
away money really difficult:
- I had to manually shuffle my inventory every time to keep
it random.
- People hated getting a stupid adamant scimitar, and those made up 50% of the prize pool!
- People wanted to
go again!
- I couldn't see who was trading me because how many people were there.
- Trying to advertise at the Grand
Exchange period was a fruitless endeavor.
-
I decided to tackle these issues one at a time, first one being how much time it took to shuffle my inventory. Fortunately for me, I've messed around with Python since 2011, and it's always come in handy when I need to do tedious computer activities. I figured, hey! Why don't I just make a random number generator, and add a prize to each number with the same odds as what's in my inventory, and it'll be like no difference! Not only that, but it will guarantee randomness every roll.
While I was creating this, I decided it was time to financially bite the bullet and up my prize game; give the people what they want! No adamant scimitars will be cluttering up my inventory anymore. Allll rune, bay bayyy!
This is what the prize pool looked like in March of 2020
Fun Fact: At this time there was actually a 1/28 chance that you would win a bond!
-
Now this solved 2 of my problems. And it was decently successful when I went back to the Grand Exchange to give things away! However, I still had people begging me to go again, or trying to claim that they never got a chance even when I knew they had. The volume of trades would get overwhelming, and it was hard to keep track of who had already gone, and who was still yet to go.
I had a general idea of how I could fix this and make giving away my money even more efficient. However, it was at about this time that my 2 week retreat from work had ended and it was back to my lame ass job. I'd go to work and just mull over ideas as to how I could keep track of people trading me.
April 2020 is when I gave the middle finger to the Grand Exchange, and walked all around World 301 to find a place where real people actually playing the game could benefit from my give-aways, as opposed to random beggars who cry and whine all day at the Grand Exchange.
I went to Lumbridge.
No dice.
I went to Hill Giants in Varrock.
It was receptive, but annoying to try and
trade people when they're already in combat.
I moved over to the fishing spot in Barbarian Village.
I was dismissed by the angry Ironmen.
It was then that I made my venture out to Karamja.
It was perfect! The people there were there to relive
the nostalgia from the old days, not 3 tick fishing trying to get to 200m xp. And best of all, there were REAL players. Conversations and jokes galore!
It was a no-brainer that the Karamja fishing docks would be the home for my give-aways.
-
Right, so at this point in time, any time I did a give-away, it was all done through the Python terminal.
All text, no colors. AND I had to manually type out the name of the player who got to go.
This resulted in awful typos because, as most of you know, I tend to do a little drinking when I give out money ;)
-
THIS is an example of what it looked like on my end when I was doing give-aways:
Explanation of this picture line by line:
1 - My program prompts me to put in a number, but this is also the same prompt I used to give every type of input to the program. In this example, I'm using the prompt to input the name of a player, BrnzeGangSuk
2 - The program reads my input, and sets the current "PLAYER" to whatever I typed in, in this case, BrnzeGangSuk
3 - The program recognizes that BrnzeGangSuk hasn't gone before, and therefore is a NEW player. (This was basically so I would know when people lie that they never got to go)
4 - Again, I'm prompted to give an input to the program. This time, I actually input the number between 1 and 28 that the player chose
5 - A Prize is generated and printed
6 - The Value of the Prize is printed
7 - Print the total winnings of the PLAYER
8 - Print the complete list of players who have gone
9 - Back to the prompt from Line 1
As you might be able to infer, this had a high probability of human error on my part, and was also kind of tedious to keep up with.
I needed a way to make the Player Selection process more streamlined and error-free.
That's when it finally clicked:
RuneLite
-
RuneLite already had a built-in function to notify you when someone traded you. I thought, "Perfect. I can just piggyback off of someone else's hard work!" And piggyback I did.
I searched on YouTube how to create a custom RuneLite plugin (which was actually a lot harder to find than I thought it would be), but I was only planning on editing an existing plugin.
Eventually, I found a helpful video that showed me how to set everything up. I wish I could remember whose it was, they deserve the recognition. But alas! my memory just isn't what it once was. Either way, I was finally set up and ready to make this happen. Uh oh, though, I needed to learn Java in order to make my dream a reality.
-
I think now would be a good time to confess that I am not a professional programmer, designer or anything, really. My Python experience started during a high school vocational program. I got to leave my high school for half the day every day my junior and senior year to go to a vocational school for "Information Technology". Some people learned 3D Modeling/Animation, some people learned C# and made games with Unity and utilized the 3D people to model for their games. One other student and myself, however, got to learn Python instead. I don't know why it was just 1 other kid and I, but I didn't mind.
I'm rambling at this point. What I'm trying to say is that I have never been professionally trained in software design/development, (went to college majoring in computer science but dropped out after day 1), and everything I learned has been mostly self taught. Self taught meaning Googling a question and searching StackOverflow until I find an answer. Ergo: I'm not a genius. Anybody could do this if they had the passion.
BACK TO IT THOUGH.
-
I needed to find a way to let my Python program see who has traded me. I honestly didn't want to learn too much Java, I just wanted to fix the problem. So here's what I ended up doing:
I just looked in RuneLite's vanilla plugins, and found that the Chat Notifications plugin was the one that would notify you when someone trades you. (Who would have thought?) All I needed to do was hijack the function that notifies you when you're traded, and instead have it send the name of the player who traded me to a .txt file.
That's it. I don't even know if that's acceptable Java practice, but it works so I don't touch it.
Then, I'd have the Python program read the text file and put every name in the .txt file in a list. I'd make it so my Python program would read said list, and randomly select people from that list to go and also put them on a new list of "players who have gone" so they don't get chosen again.
-
After this was made, Re-rolling and The Queue were created.
Pretty much everything about Re-rolling and The Queue has remained the same since its creation, with slight tweaks and alterations over the year.
If you'd like a more in depth look at how all of those work, check out the Player Selection page from the Mechanics section of the website.
-
These were the game changers I needed to make my life easier. From that point on, I was free to focus on ideas on how to make the game more exciting for the players.
And thus, the Random Double was born.
That's right, you spoiled fishers, back in MY day we didn't have these fancy-pants Triples and Quadruples. The ONLY multiplier that was around was the new Random Double.
Actually, I don't think anything about the Random Double has changed since it was first created. It's always been a 9/128 chance to hit ever since it was released.
And because the Random Double was such a thrill to see, sometime within the month of May, the Random Triple was included, again, not changing since its implementation.
-
During the rest of the month of May, I had started working on a (for now removed) feature: TRIVIA!
For the OGs who remember Trivia, I'll have you know that it was so haphazardly put together and untested, that almost every time I would do the Trivia feature, some bug would occur and the whole give-away program would crash.
This is why I always decided to do Trivia at the end of my give-aways ;)
But! For those curious about what it used to be, it was just random Old School Runescape Trivia comprised of only F2P skills.
The basic template for a Trivia question was
"What {SKILL} level do you need to {MAKE/EQUIP/CAST/PRAY etc.} {ITEM FROM THE SKILLS MENU}?"
For instance, a typical trivia question would look like:
What WOODCUTTING level do you need to CHOP YEW LOGS?
The first player to give the correct answer (60) would then get a chance to choose a number and roll like normal.
Similarly to how I found out the names of players who traded me, I used the Chat Notifications plugin from RuneLite to be able to see just who answered the question correctly first.
This feature was eventually scrapped because I didn't like the lack of variety in the questions, and also, people could spam answers before I even asked the question, and if they randomly guessed the answer, they would win.
Chalk it up to laziness and spaghetti code, but I just never felt like fixing it.
-
The month of May also introduced a new and improved Prize-Pool! This meant I had arranged a huge variety of prizes instead of the typical boring Rune items.
Not only that, but I had also tried to create different tiers of drop tables to try and mimic how Runescape drops work.
The NEW New Prize-Pool and the different drop tables.
As you can see, not too much has changed from this Prize-Pool over the past year (currently writing this on May 11, 2021), but I did move some prizes around to different tables.
-
I'd like to get into how I worked out the odds for the tables, but I'm looking back on my code and I honestly have no idea what I'm even looking at. Whatever I did must have been some THC and alcohol induced logic, because I can't make sense of it.
I do know, however, that I created a function in the program that would simulate 1,000,000 rolls and would show me the results of what prizes were chosen. From those results, I would adjust the odds of winnings prizes until they were where I wanted them.
Just a little explanation of what you're looking at, it goes:
{Name of Item} - {Amount of times won} - {% of times won}
-
It was from this point on where I had the basic foundation set for the entire game, and could just keep adding on to it whenever I thought of a fun idea.
Oh, speaking of which, enter Risky Doubles.
The final addition to the game for the month of May was Risky Doubling. It was something I was really hesitant of implementing at first, because I still didn't really have that much of a reputation, and I didn't want people to think I'm just the typical "Money Doubler" you see at the Grand Exchange. (Have I mentioned how much I loathe the Grand Exchange crowd?)
My original thought of Risky Doubling was that it was really a chance for me to save some money to keep the game going, while simultaneously giving players an extra fun feature for prizes they don't care about.
Happily enough, folks at the docks seemed to be really excited to try to double their prize, and even more excited when someone hit it.
Honestly, it made the game even more exciting for ME as well, as I'd be up in suspense to see if the player would successfully double or not, and then be absolutely hyped when they did.
This opened up a whole new door for features the game could have.
June was a lot of fun, however, there weren't too many changes made in the game during this month.
If I recall correctly, my job had began getting busy again after the initial COVID outbreak. I was an electrician, and I would just come home tired as hell. I believe at that time we were doing 3 different solar projects.
-
So unfortunately, there isn't much to speak of for the month of June. But hey, check out this screenshot I apparently accidentally took after finishing up a night of giving money away.
This is how I operated back in the day; RuneLite on the left, and my insane sea-of-text of a Python console on the right.
Everything that started with a "!" was a command that I sent to the program.
The month of July was awesome.
Due to the almost overwhelming love for the Risky Double, I decided to introduce the Risky Triple, the Risky Double's cooler cousin.
Again, the new addition received much praise and a lot of engagement.
But I wanted to do something to add a little something something more to the game.
-
For The 4th of July, I decided to implement a whole new Random Multiplier, the infamous Random Quadruple.
Not only did I add the Random Quadruple to the game, but I also had a little "event" for the 4th so that Random Multipliers were MUCH more likely to be rolled.
I also had a fun little challenge going where I promised that whoever was the first person to hit the Random Quadruple would also instantly win a Bond. This just added to the excitement and anticipation.
-
Now at this point in my personal life, I was so sick of my job and also the state I lived in (Vermont).
My girlfriend and I had been planning to eventually move out to Arizona because we both loved it out here and hate the snow.
For context: she was born and raised in Arizona, and I was born and raised in Maine.
After 2 decades of 8 months a year of winter, I grew to hate the snow and New England weather in general.
Anyway, one day I was just so fed up with the constant communication problems with the company I was working for, that I came home and talked to my girlfriend about just up and moving out to Arizona immediately.
Fortunately, we had both been saving up enough to realistically be able to afford it, and so, I pulled the trigger, put in my 2 weeks notice, and began apartment and job searching for Arizona.
-
Thus began the slow conclusion of the last few months of give-aways as we eventually made the move in August.
After moving, I didn't really play Runescape too much. And so, the give-away fizzled out of existence.
Note: All the above sections were written on 5/11/2021. I am just now sitting down and adding another entry to this on 11/5/2022. much has changed since then, and I will try to accurately recall things, but no guarantees that I'll be correct. ;)
Picking up where we left off - I had moved out to Arizona in August 2020 and stopped playing Runescape as much as I previously had.
HOWEVER, during this time, I had been practicing with creating GUIs in Python using Tkinter. This was something I had originally tried long ago but did not pick up on it and just avoided my whole life. At some point I decided enough was enough and I had to buckle down and learn.
I had decided that my ultimate exercise for learning Tkinter would be to create the Giveaway in a way that I wouldn't have to look through a sea of text in a console to operate the game; I could have a nice GUI with colors and buttons and information!
I also wanted to implement the idea of data tracking so people could see how much they've won and how much I've given out over all of these sessions. I managed to find a solution! But the way I did this was super hacky and I don't even want to talk about it.
-
Alright, I'll talk, I'll talk.
So, I had to pretty much find a way to store data for any player that would play, but also store it separately from the Giveaway program itself, so the data wouldn't just reset every time I ran the Giveaway program.
Not only that, but I would also need to have the program read and interact with this data to display during the Giveaway.
The only type of external file manipulation I had experience with was with .txt files, and something told me that using a text file to store all of this information was NOT a good call.
I ended up storing all the data for this entire game in 3 separate .ini files: game_data.ini, player_data.ini, and roll_data.ini.
Yeah, .ini files; configuration files.
-
ANYWAY, I knew I was building the foundation of my data tracking on something rocky, but I had no idea just how problematic it could be down the road. But we'll get there when we get there.
So, every time a New Player traded me, a new entry would be created in the player_data.ini file with all of their information like this:
Fun Fact: ShuggieK was the first person to trade me since I started keeping track of data on 03/01/2021.
Also check out that "standing" parameter. I was originally going to use it to flag people who end up being
disruptive, but I never actually had to use it because you guys rock.
-
The general Game Data was kept in the game_data.ini file that looked like this:
The Jackpot didn't come out until May, but I don't have any backups of the Giveaway 2 files predating May of 2021
-
I'm sure you all get the idea, but I'm going to share what the roll_data.ini looked like as well. This is oddly enough where I kept all the data for each and every roll that happened in the Giveaway:
The "Real Roll Number" is the number that was chosen in the spinner analogy explained HERE
-
While these pictures are all fine and dandy, allow me to introduce the REAL looker of the Giveaway program, the GUI:
I was, and still am, super proud of this. It made me life soooooooooo much easier than before and I could really focus on just adding more and more to the game now that the gameplay was smooth on my end.
What's that? You want a tour of what's going on here? Say no more!
-
Let's start off with the lower left (uneven) quarter of the GUI. This is where I had all my buttons to control most of the general things I needed to do:
The Giveaway starts once I press that Green "Advertise" button. That's what triggers me to say "Yo. Trade Actually Tim for free stuff".
I used to actually need the Advertise button because I never used to have this many regular players, and I couldn't reroll players unless
there were a certain number of total players first.
After I do the initial advertisement, the four buttons at the top become usable. Clicking the "Check Trades" button reads the trades.txt file explained HERE and populates the list of Players to choose from. If there are any New Players, the Roll button will be highlighted green, and once pressed, selects the next Player.
The Re-roll button is what I press when there are no more New Players and we move on to rerolls. This triggers the Player selection explained HERE.
The Slow Message button is what sends the "reminder" message to the player when they're taking too long. 3 Presses and they get skipped.
The Over-Trader, High Roller, Top Winner etc. buttons are used to announce their respective title holders; it was just information that was so frequently requested that I made convenient buttons for quick access.
The Jackpot button announces the current value of the Progressive Jackpot, and the number below it is the current value.
The final lower section buttons aren't really used in the Giveaway, but are more for testing and maintenance purposes.
The text entry field is paired with the Test Rolls button below it. I can type in a number of rolls to simulate and the program would simulate that number.
Honestly, I don't recall what the Jackpot Test button was for, it was probably just something I never got rid of after finishing implementing the Jackpot in May.
Finally, the Get HTML Codes button takes up such a small portion of the GUI, but it is a huge part of the website. It is worth noting that this GUI screenshot is from a backup from July 2021, and the website was not yet around in March. Aside from that, since I did not yet have the knowledge and skill to let my python program communicate with my website, the workaround would be that at the end of every session, I would hit that button, and the program would read all of the current data for each player and compile them into their respective leaderboards.
It would also compile all of the rolls to make the Roll History page.
If you ever saw me say something like "Alright, I'm gonna reset the list, update the site, and I'll be right back!", the "update the site" part was me uploading all of the files that this button generated to the website.
-
Moving on to the upper left quarter. This is where all of the rolling takes place. Once a player is selected, it looks like this:
Unfortunate example
Once the player gives me the number they choose, I manually type that number into the little field at the top and press ROLL. That is when the prize is generated for the player.
The name and value of the prize is then displayed so I can make sure I'm giving out the correct item.
Once that happens, I then trade the player the item that they've won, and once they've accepted the prize, I press Confirm Trade and it locks in the roll and updates the stats for the game and Player.
If they want to try to multi their prize, I'll press the correct button. Simple, right?!
-
Moving on to the next part, I call this one the Player Controller. It's pretty much where I can access data for Players and relay the information to them. Like how much have they won this session? What about all time? Are they in the list?
I can just type their name in the SEARCH for them to see if I have any data on them:
Starting in the lower section, the Trades, Winnings, Rolls etc. buttons would announce the value of the respective statistic for whichever Player was searched above.
I also had a little "how many players left" counter in this section so I could quickly see it.
The top section is where the real control is. As you can see, I can Add or Remove the Player that was typed into the search bar. I can also Re-roll a player this way, but I only use this when a Player just barely misses their turn, or if I am adding an Ironman to the game. (This is the only way I can add Ironmen to the Giveaway)
-
Finally, the stat display part of the GUI. This was really handy to riddle off some stats at people when they asked, or if I was at the end of the game and just wanted to share all I had.
Again, this was before the website was created, so nobody knew about all of this data except for me. This was the only way I could share.
It doesn't look like it, but each of those numbers are actually buttons I could click to announce the data for whichever statistic I wanted to share.
That just about sums up all of the changes that were made from July 2020 to March 2021. The complete transformation of the Giveaway to Giveaway 2. It was amazing to see the progress of what this started as and what it had become. But there was still so much more ahead.